<template>
    <div>
        <div ref="chartContainer" id="chartContainer"></div>
    </div>
    <div
        id="customTooltip"
        style="
            position: absolute;
            display: none;
            background: rgba(0, 0, 0, 0.7);
            color: #fff;
            padding: 5px 10px;
            border-radius: 4px;
            pointer-events: none;
            font-size: 16px;
            z-index: 999;
        "
    ></div>
</template>

<script setup lang="ts" name="RingChartV3">
    import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
    import Circos from 'circos';
    import * as d3 from 'd3';
    import { jsPDF } from 'jspdf';
    import { svg2pdf } from 'svg2pdf.js';

    defineExpose({
        downloadPdf
    });

    const props = defineProps(['cnData', 'geneData', 'chromData', 'label_denominator', 'spacing']);
    const width = 500;

    function showTooltip(html: any, x: any, y: any) {
        const tooltip: any = document.getElementById('customTooltip');
        tooltip.innerHTML = html;
        tooltip.style.left = `${x + 10}px`;
        tooltip.style.top = `${y + 10}px`;
        tooltip.style.display = 'block';
    }

    function hideTooltip() {
        const tooltip: any = document.getElementById('customTooltip');
        tooltip.style.display = 'none';
    }

    const chartContainer: any = ref(null);
    let circos: any = null;

    const updateChart = () => {
        if (chartContainer.value) {
            chartContainer.value.innerHTML = '';
        }

        const chromConfig = {
            innerRadius: width / 4.5 - 15,
            outerRadius: width / 4.5,
            labels: {
                display: false
            },
            ticks: {
                display: props.chromData.length > 8 ? false : true,
                color: 'grey',
                spacing: props.spacing,
                labels: true,
                labelSpacing: 10,
                labelSuffix: 'Mb',
                labelDenominator: props.label_denominator,
                // labelDisplay0: true,
                labelSize: '10px',
                // labelColor: '#000000',
                // labelFont: 'default',
                // majorSpacing: 5,
                size: {
                    minor: 2,
                    major: 5
                }
            },
            tooltipContent: function (datum: any, index: any) {
                return `<h5>segement:${datum.id} ${datum.label}:${datum.originStart}-${datum.originEnd} ➤ ${datum.len}</h5>`;
            },
            events: {
                mouseenter: function (d: any, i: any, nodes: any, event: any) {
                    const content = chromConfig.tooltipContent(d, i);
                    showTooltip(content, event.pageX, event.pageY); // 你自己写个 showTooltip 函数
                },
                mouseleave: function (d: any, i: any, nodes: any, event: any) {
                    hideTooltip(); // 鼠标移开隐藏
                }
            }
        };

        const chromLabelTextConfig = {
            innerRadius: width / 4.5 + 55, // 放置在 ideogram 外边缘
            outerRadius: width / 4.5 + 65, // 标签的径向范围，可以调整以避免重叠
            style: {
                'font-size': '20px', // 标签字体大小
                fill: '#333333' // 标签颜色
            },
        };

        const chromTextData = props.chromData.map((item: any) => ({
            block_id: item.id, // 对应布局中的数据段ID
            position: item.len / 2, // 标签的中心位置
            value: item.label // 标签文本
        }));

        const geneConfig = {
            innerRadius: 0.9,
            outerRadius: 0.8,
            padding: 0.005,
            // labels: {
            //     display: true,
            //     size: 12,
            //     radialOffset: 20
            // },
            // logScale: true,
            // color: '#426e93',
            tooltipContent: function (datum: any, index: any) {
                return `<h5>${datum.name}:${datum.originStart}-${datum.originEnd} ➤ ${datum.value}</h5>`;
            }
        };

        const cnConfig = {
            innerRadius: 0.6,
            outerRadius: 0.8,
            // color: (d: any) => cnColorScale(d.value),
            color: '#913028',
            strokeColor: '#fff', // 柱子间的线
            fillOpacity: 0.8,
            tooltipContent: function (datum: any, index: any) {
                return `<h5>position: ${datum.originStart} ➤ ${datum.value}</h5>`;
            }
        };

        const geneLabelConfig = {
            innerRadius: 0.8,
            outerRadius: 0.9,
            labelSpacing: 5,
            labelSize: 12,
            color: '#333333',
            labelColor: '#333333',
            labelFont: '12px sans-serif'
            // tooltipContent: function (datum, index) {
            //     return `<h5>${datum.value}</h5>`;
            // }
        };

        const geneTextData = props.geneData.map((item: any) => ({
            block_id: item.block_id,
            position: (item.start + item.end) / 2,
            value: item.name
        }));

        circos = new Circos({
            container: chartContainer.value,
            width: width,
            height: width
        });

        circos
            .layout(props.chromData, chromConfig)
            .heatmap('gene', props.geneData, geneConfig)
            .histogram('cn', props.cnData, cnConfig)
            .text('chromLabels', chromTextData, chromLabelTextConfig) // 添加自定义标签轨道
            .render();

        setTimeout(() => {
            const labels:any = d3.select(chartContainer.value).selectAll('g.chromLabels text');
            console.log(labels);
            labels
                .attr('text-anchor', 'middle')
                .attr('dominant-baseline', 'central')
                .each(function (datum:any, i:any, nodes:any) {

                    const el = nodes[i];

                    // 2. 从它原有的 transform 中解析 translate(x,y)
                    const tf = el.getAttribute('transform') || '';
                    const newTf = tf.replace('rotate(0)', 'rotate(90)');
                    console.log(newTf);
                    // 应用属性
                    d3.select(el).attr('transform', newTf);
                });
        }, 10);
    };

    /**
     * 点击按钮时：抓取当前 SVG，转成 PNG via Canvas，然后嵌入 PDF 并下载
     */
    function downloadPdf() {
        const svgEl = chartContainer.value.querySelector('svg');
        if (!svgEl) return;

        const { width, height } = svgEl.getBoundingClientRect();
        const scale = 3;
        const canvas = document.createElement('canvas');
        canvas.width = width * scale;
        canvas.height = height * scale;
        const ctx: any = canvas.getContext('2d');

        const svgString = new XMLSerializer().serializeToString(svgEl);
        const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
        const url = URL.createObjectURL(blob);
        const img = new Image();
        img.onload = () => {
            ctx.imageSmoothingEnabled = false; // 关闭抗锯齿
            ctx.scale(scale, scale);
            ctx.drawImage(img, 0, 0);
            URL.revokeObjectURL(url);

            const imgData = canvas.toDataURL('image/svg', 1.0);
            const pdf = new jsPDF({
                orientation: width > height ? 'landscape' : 'portrait',
                unit: 'px',
                format: [canvas.width, canvas.height]
            });
            pdf.addImage(imgData, 'JPG', 0, 0, canvas.width, canvas.height);
            pdf.save('circos_chart.pdf');
        };
        img.src = url;
    }

    watch([() => props.chromData, () => props.cnData, () => props.geneData], updateChart, { deep: true });

    onMounted(async () => {
        updateChart();
    });
</script>
<style lang="scss" scoped>
    #chartContainer {
        width: 100%;
        height: 420px;
        display: flex;
        justify-content: center;
        margin-top: -6%;
    }
</style>
